package encodingSimulation;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Random;

public class EncodingHelper {
	EncodingImplementation encoder ;
	public EncodingHelper(EncodingImplementation encoder) {
		this.encoder= encoder;
	}

	public BitSet byteArrayToBitSet(byte[] input) {
		int length = input.length;
		BitSet set = new BitSet(length * 8);
		set = BitSet.valueOf(input);
		// for (int i = 0; i < length; i++)
		// {
		// if (input[i] != 0)
		// set.V;
		// }
		// System.out.println(" length of bitset"+set);
		return set;

	}

	public int[][] matrixTranspose(int[][] generator) {
		int[][] transpose;
		int rows = encoder.getNumberOfSourceFragments();
		int cols = encoder.getTotalEncodedPackets();
		transpose = new int[cols][rows];

		for (int h = 0; h < rows; h++) {
			for (int i = 0; i < cols; i++) {
				transpose[i][h] = generator[h][i];
			}
		}

		return transpose;
	}

	public void writeToFile(File filename, String data) {
		PrintWriter pw = null;
		try {
			pw = new PrintWriter(filename);
			pw.print(data);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		pw.close();

	}

	public String getMD5Checksum(File filename) throws Exception {
		byte[] b = createChecksum(filename);
		String result = "";

		for (int i = 0; i < b.length; i++) {
			result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
		}
		return result;
	}

	public byte[] createChecksum(File filename ) throws Exception {
//		EncodingImplementation e = new EncodingImplementation();
		byte[] buffer = new byte[this.encoder.getFragmentSize()];
		RandomAccessFile r = new RandomAccessFile(filename, "r");
		MessageDigest complete = MessageDigest.getInstance("MD5");
		int numRead;
//		StringBuffer fileData = readFile(filename);
		int fragmentSize = encoder.getFragmentSize();
		int max = encoder.getSourceFileLength() / fragmentSize;
		
		byte[] b = new byte[fragmentSize] ;
		int newPos=0;
		int i = 0;
		do {
//			int startPos = i * this.encoder.getFragmentSize();
//			int endpos = startPos + this.encoder.getFragmentSize();
//			numRead = endpos - startPos;
//			buffer = fileData.substring(startPos, endpos).toString().getBytes();
			i++;
			numRead=r.read(b ,0, fragmentSize );
//			System.out.println(new String(b));
			newPos=fragmentSize*i;
			r.seek(newPos);
			if (numRead > 0) {
				complete.update(buffer, 0, numRead);
			}
//			i = i + 1;
		} while (numRead != -1 && i < max);
		return complete.digest();
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see encodingSimulation.EncodingMethods#readFile(java.lang.String)
	 */
	public StringBuffer readFile(File file) {
		File fileName= file;
		FileReader fis = null;
		BufferedReader bis = null;
		StringBuffer fileContent = new StringBuffer();
		try {
			fis = new FileReader(fileName);
			bis = new BufferedReader(fis);
			String line = null;
			while ((line = bis.readLine()) != null) {
				fileContent.append(line);
			}
			fis.close();
			bis.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return fileContent;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see encodingSimulation.EncodingMethods#fragmentFile(java.lang.String)
	 */

	public ArrayList<byte[]> fragmentFile(String data) {

		String[] stringSourceFragments = new String[this.encoder.getNumberOfSourceFragments()];
		for (int i = 0; i < encoder.getNumberOfSourceFragments(); i++) {
			// the substring starts here
			int startPos = i * encoder.getFragmentSize();

			// the substring ends here
			int endPos = startPos + encoder.getFragmentSize();

			// make the substring
			String substr = data.substring(startPos, endPos);

			// stick it in the result array
			stringSourceFragments[i] = substr;
			//System.out.println(" value of fragment is"
			//	+ sourceFragments[i].length());
		}
		ArrayList<byte[]> sourceFragments = new ArrayList(); 
		for( int j=0;j<encoder.getNumberOfSourceFragments() ;j++){
			byte[] temp = stringSourceFragments[j].getBytes();
			//System.out.println(new String(temp));
			sourceFragments.add( temp);
		}
		return sourceFragments;
	}
	public int[][] createGeneratorMatrix(int option) {
		Random random = new Random();
		int[][] matrix = new int[encoder.getNumberOfSourceFragments()][encoder.getTotalEncodedPackets()];
		for (int outerIndex = 0; outerIndex < matrix.length; outerIndex++) {
			for (int innerIndex = 0; innerIndex < matrix[outerIndex].length; innerIndex++) {
				if (random.nextDouble() < 0.5) {
					matrix[outerIndex][innerIndex] = 1;
				} else {
					matrix[outerIndex][innerIndex] = 0;
				}
			}
		}
		return matrix;
	}

	public ArrayList<BitSet> fragmentSourceData(File filename) {
		RandomAccessFile r ;
		ArrayList<BitSet> sourceBits = new ArrayList<BitSet>();
		
		try {
			r= new RandomAccessFile(filename, "r");
			System.out.println(r.length());
			encoder.setSourceFileLength((int)r.length());
			int fragmentSize = encoder.calculateFragmentSize();
			System.out.println(fragmentSize);
			encoder.setFragmentSize(fragmentSize);
			encoder.setParameters();
			
			byte[] b = new byte[fragmentSize] ;
		
				long new_pos=0;
				int i=0;
				while(new_pos<=encoder.getSourceFileLength()){
					i++;
					r.read(b ,0, fragmentSize );
//					System.out.println(new String(b));
					new_pos=fragmentSize*i;
					r.seek(new_pos);
					sourceBits.add(BitSet.valueOf(b));
				}
				r.close();
				b=null;
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return sourceBits;
	}
}
